Ruby 日記 4日目: モジュールをextendするとそのモジュールのインスタンスメソッドがselfの特異メソッドとして追加される
次のコードを実行するとどうなりますか
code:gold/ex04/main.rb
module M
def class_m
"class_m"
end
end
class C
extend M
end
p C.methods.include? :class_m
選択肢:
trueが表示される
falseが表示される
nilが表示される
警告が表示される
解説:
includeかextendかの違いだね
引数で指定したモジュールのインスタンスメソッドを self の特異 メソッドとして追加します
つまり、今回の問題だとモジュールMの
code:m.rb
def class_m
"class_m"
end
というメソッド定義が、クラスCの特異メソッド(クラスメソッド)として追加される。
すなわち、こういうこと。
code:c.rb
class C
def self.class_m
"class_m"
end
end
なので、p C.methods.include? :class_m は
「クラスCに対して呼び出せるクラスメソッドに :class_m は含まれますか?」という問いである。答えは true だね
code:sh
# ruby gold/ex04/main.rb
true
/icons/hr.icon
そのオブジェクトに対して呼び出せるメソッド名の一覧を返します。 このメソッドは public メソッドおよび protected メソッドの名前を返します。
ただし特別に、引数が偽の時は Object#singleton_methods(false) と同じになっています。
とある。
そのオブジェクトに対して定義されている特異メソッド名 (public あるいは protected メソッド) の一覧を返します。
前者は「そのオブジェクトに対して呼び出せるメソッド名」
後者は「そのオブジェクトに対して定義されている特異メソッド名」
code:gold/ex04/methods_and_singleton_methods.rb
module Bar
private; def private_bar() end
protected; def protected_bar() end
public; def public_bar() end
end
class Foo
extend Bar
class << self
private; def private_self() end
protected; def protected_self() end
public; def public_self() end
end
end
p Foo.methods
p Foo.methods(false)
p Foo.singleton_methods(false)
p Foo.singleton_methods(true)
code:sh
# ruby gold/ex04/methods_and_singleton_methods.rb
:protected_self, :public_self, :protected_bar, :public_bar, :allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__ Foo.methods
Fooクラスに対して呼び出せるメソッドたちぜんぶ(たくさん)
privateメソッドは当然含まれない(呼び出せないので)
Foo.methods(false), Foo.singleton_methods(false)
Fooクラスに対して定義されているメソッドたち
privateメソッドは含まれない
Foo.singleton_methods(true)
Barモジュールをextendしたことによって追加されたクラスメソッドを含む
継承した特異メソッドとは Object#extend によって追加された特異メソッドや、 self がクラスの場合はスーパークラスのクラスメソッド(Classのインスタンスの特異メソッド)などです。
privateメソッドは含まれない